using Godot;
using System;
using System.Collections.Generic;
using Common;
using File = Common.File;
namespace Library {
	public class SpriteController : Sprite {
		static SpriteController() {
			List<string> collections = new JsonFile<List<string>>("res://Textures/Collections.json").Source;
			foreach (string file in collections) {
				LoadCollection(file);
			}
		}
		static bool LoadCollection(string path) {
			if (!File.IsExists(path)) {
				return false;
			}
			Collection sc = new JsonFile<Collection>(path).Source;
			if (sc.Groups.Count <= 0) {
				return false;
			}
			collections[sc.Name] = new Dictionary<string, Group>();

			foreach (KeyValuePair<string, Group> pair in sc.Groups) {
				collections[sc.Name][pair.Key] = pair.Value;
			}
			GD.Print("[SpriteController] Loaded collection ", sc.Name, " from ", path);
			return true;
		}
		public class Collection {
			public string Name { get; set; } = "NewCollection";
			public Dictionary<string, Group> Groups { get; set; } = new Dictionary<string, Group>();
		}
		public class Group {
			public Group(params string[] sprites) {
				Sprites = sprites;
			}
			public string[] Sprites { get; set; }
			public float Speed { get; set; } = 6;
			public bool StartPlaying { get; set; } = true;
			public float StartIndex { get; set; } = 0;
			public bool Looped { get; set; } = true;
			public bool FlipX { get; set; } = false;
			public bool FlipY { get; set; } = false;
			public string GroupWhenEnd { get; set; } = "";
			public bool Centered { get; set; } = true;
			public Vector2 Origin { get; set; } = new Vector2(0, 0);
		}
		public static Dictionary<string, Dictionary<string, Group>> collections = new Dictionary<string, Dictionary<string, Group>>();

		[Export]
		public string CollectionIndex { get; set; } = "";
		string collectionIndexPrevious = "";
		[Export]
		public string GroupIndex { get; set; } = "";
		string groupIndexPrevious = "";
		public float Index = 0;
		public float SpeedScale = 1f;
		public bool Playing = true;

		Dictionary<string, Group> currentCollection = null;
		Group currentGroup = null;
		Dictionary<string, Texture> loadedTextures = new Dictionary<string, Texture>();

		public override void _Process(float delta) {
			if (CollectionIndex != collectionIndexPrevious) {
				currentCollection = null;
				currentGroup = null;
				if (collections.ContainsKey(CollectionIndex)) {
					currentCollection = collections[CollectionIndex];
				}
				collectionIndexPrevious = CollectionIndex;
				groupIndexPrevious = "";

				loadedTextures.Clear();
				GD.Print("LoadedTextures: ", loadedTextures.Count);
			}

			if (GroupIndex != groupIndexPrevious) {
				currentGroup = null;
				if (currentCollection != null && currentCollection.ContainsKey(GroupIndex)) {
					currentGroup = currentCollection[GroupIndex];
					Playing = currentGroup.StartPlaying;
					if (currentGroup.StartIndex >= 0) {
						Index = currentGroup.StartIndex;
					}
				}
				groupIndexPrevious = GroupIndex;
			}

			if (currentGroup != null) {
				int spriteCount = currentGroup.Sprites.Length;
				if (spriteCount <= 0) {
					return;
				}

				if (Playing) {
					Index += currentGroup.Speed * SpeedScale * delta;
				}
				if (currentGroup.Looped) {
					while (Index >= spriteCount) {
						Index -= spriteCount;
					}
					while (Index < 0) {
						Index += spriteCount;
					}
				} else {
					if (Index > spriteCount) {
						Playing = false;
						Index = spriteCount - 1;
						if (!string.IsNullOrWhiteSpace(currentGroup.GroupWhenEnd) && currentCollection.ContainsKey(currentGroup.GroupWhenEnd)) {
							GroupIndex = currentGroup.GroupWhenEnd;
						}
					}
					if (Index < 0) {
						Index = 0;
					}
				}
				string spritePath = currentGroup.Sprites[(int)Math.Floor(Index)];
				if (!loadedTextures.ContainsKey(spritePath)) {
					Texture tex = GD.Load<Texture>(spritePath);
					loadedTextures.Add(spritePath, tex);
					//GD.Print("LoadedTextures: ", loadedTextures.Count);
				}
				Texture = loadedTextures[spritePath];
				FlipH = currentGroup.FlipX;
				FlipV = currentGroup.FlipY;
				Centered = currentGroup.Centered;
				Offset = new Vector2((!FlipH ? -currentGroup.Origin.x : -Texture.GetWidth() + currentGroup.Origin.x), (!FlipV ? -currentGroup.Origin.y : -Texture.GetHeight() + currentGroup.Origin.y));
			}
		}
	}
}
